/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package parsing;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *
 * @author dema0614
 */
public class JavaClassParser {

    private String classText;

    private final Pattern patternForFields = Pattern.compile("(private\\s+|public\\s+|protected\\s+)?" +
                                                             "(static\\s+|final\\s+|final\\s+static\\s+|static\\s+final\\s+)?" +
                                                             "[A-z]\\w*" +
                                                             "(\\s+|" +
                                                             "\\s*\\[\\s*\\]\\s+|" +
                                                             "\\s*\\[\\s*\\]\\s*\\[\\s*\\]\\s+|" +
                                                             "\\s*<\\s*([A-z]\\w*\\s*)?>\\s+)" +
                                                             "[A-z]\\w*\\s*" +
                                                             "(\\[\\s*\\]\\s*|" +
                                                             "\\[\\s*\\]\\s*\\[\\s*\\]\\s*)?" +
                                                             "(;|(=\\s*" +
                                                             "(\".*?(\")|\\{.+\\}|" +
                                                             "[A-z].*\\(.*\\)|\\d+|" +
                                                             "[A-z]\\w*)" +
                                                             "\\s*;)" +
                                                             ")", Pattern.COMMENTS);

    private final Pattern patternForMethods = Pattern.compile("(private\\s+|public\\s+|protected\\s+)?\n" +
                                                              "(static\\s+|final\\s+|final\\s+static\\s+|static\\s+final\\s+)?\n" +
                                                              "[A-z]\\w*(((\\s*\\[\\s*\\]\\s*)*)|(<\\s*[A-z]\\w*\\s*>)?)\\s+\n" +
                                                              "[A-z]\\w*(\\s*\\[\\s*\\]\\s*)*\\s*\n" +
                                                              "[(][^)]*[)]\\s*(?=\\{)", Pattern.COMMENTS);

    private final Pattern patternForReference = Pattern.compile("!referece to class (\\d+);");

    public JavaClassParser(String classText) {
        this.classText = classText;
    }

    public List<String> extractFields() {
        Matcher matcher = patternForFields.matcher(classText);
        List fields = new ArrayList<String>();

        while (matcher.find()) {
            fields.add(matcher.group());
        }

        return fields;
    }

    public List<Method> extractMethods() {
        Matcher matcher = patternForMethods.matcher(classText);
        List<Method> methods = new ArrayList<Method>();

        while (matcher.find()) {
            Method method = new Method(matcher.group());
            String methodBody = classText.substring(matcher.end() + 1, findCoupledBracket(matcher.end() + 1));

            method.setBody(methodBody);
            methods.add(method);
        }

        return methods;
    }

    public int extractReference() {
        Matcher matcher = patternForReference.matcher(classText);
        int index = -1;

        if (matcher.find())
            index = Integer.parseInt(matcher.group(1));

        return index;
    }

    private int findCoupledBracket(int begIndex) {
        char[] charSC = classText.toCharArray();
        Stack stack = new Stack();
        stack.push('{');

        for (int i = begIndex; i < charSC.length; i++) {
            if (charSC[i] == '{') {
                stack.push('{');
            } else if (charSC[i] == '}') {
                stack.pop();
            }

            if (stack.isEmpty()) {
                return i;
            }
        }
        return -1;
    }

    public List<String> split(final String source) {
        int start = 0;
        ArrayList<String> list = new ArrayList<>();

        for (int i = 0; i < source.length(); i++) {

            if (source.charAt(i) == ';'
                || source.charAt(i) == '{'
                || source.charAt(i) == '}'
                || source.charAt(i) == '\"'
                || source.charAt(i) == '\'') {

                if (source.charAt(i) == '\"'
                    || source.charAt(i) == '\'') {

                    for (int j = i + 1; j < source.length(); j++) {
                        //Find pair qoute
                        if (source.charAt(j) == source.charAt(i)
                            && source.charAt(j - 1) != '\\') {

                            for (int k = j + 1; k < source.length(); k++) {
                                if (source.charAt(k) == ';') {
                                    String substr = source.substring(start, k).trim();
                                    if (!"".equals(substr)) {
                                        list.add(substr);
                                    }
                                    start = k + 1;
                                    i = start;
                                    break;
                                }
                            }
                            break;
                        }
                    }

                } else {

                    String substr = source.substring(start, i).trim();
                    if (!"".equals(substr)) {
                        list.add(substr);
                    }
                    start = i + 1;
                    i = start;
                    
                }

            }
        }
        return list;
    }

}
